package com.easygem.controller.front;

import com.easygem.common.annotation.ControllerEndpoint;
import com.easygem.common.model.front.Industry;
import com.easygem.common.model.front.TaskPackageResource;
import com.easygem.common.model.front.TaskPackage;
import com.easygem.common.response.ResponseBean;
import com.easygem.common.response.ResponseMessage;
import com.easygem.common.utils.ExcelUtils;
import com.easygem.common.vo.front.ResourceInfoVO;
import com.easygem.common.vo.front.TaskPackageResourceVO;
import com.easygem.common.vo.front.TaskPackageVO;
import com.easygem.common.vo.system.PageVO;
import com.easygem.front.service.IndustryService;
import com.easygem.front.service.TaskPackageResourceService;
import com.easygem.front.service.TaskPackageService;
import com.easygem.front.service.imp.TaskPackageResourceServiceImpl.ImportStats;
import com.easygem.front.mapper.TaskPackageMapper;
import com.wuwenze.poi.ExcelKit;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 李鹏志
 * @version 1.0
 * @Description 任务包资源管理
 * @date 2024/12/23 18:47
 */
@Api(tags = "任务包资源管理")
@Controller
@Transactional
@RequestMapping("/tasking")
@Slf4j
public class TaskPackageResourceController {
    @Autowired
    private TaskPackageResourceService taskPackageResourceService;
    @Autowired
    private IndustryService industryService;
    @Autowired
    private TaskPackageService taskPackageService;
    @Autowired
    private TaskPackageMapper taskPackageMapper;
    
    // 添加临时文件存储路径配置
    @Value("${file.upload.temp-path:/tmp/chunks}")
    private String tempPath;
    
    // 用于存储分片上传状态的Map
    private static final Map<String, Integer> UPLOAD_PROGRESS = new ConcurrentHashMap<>();
    
    // 添加用于存储导入统计信息的Map
    private static final ConcurrentHashMap<Integer, ImportStats> importTaskStats = new ConcurrentHashMap<>();

    @Autowired
    private Environment environment;

    @ApiOperation(value = "已分配任务资源列表", notes = "模糊查询已分配任务资源列表")
    @GetMapping("/allocated/getAllocatedList")
    @ResponseBody
    public ResponseBean<PageVO<TaskPackageResource>> getAllAssignedResources(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
    @RequestParam(value = "pageSize", defaultValue = "7") Integer pageSize,
    TaskPackageResourceVO tPResourceVO
    ){
        PageVO<TaskPackageResource> tPResourceList = taskPackageResourceService.getAllAssignedResources(pageNum, pageSize, tPResourceVO);
        return ResponseBean.success(tPResourceList);
    }

    @ApiOperation(value = "未分配任务资源列表", notes = "模糊查询未分配任务资源列表")
    @GetMapping("/undistributed/getNotAssignedList")
    @ResponseBody
    public ResponseBean<PageVO<TaskPackageResource>> getNotAssignedResources(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                                                             @RequestParam(value = "pageSize", defaultValue = "7") Integer pageSize,
                                                                             TaskPackageResourceVO tPResourceVO
    ){
        PageVO<TaskPackageResource> tPResourceList = taskPackageResourceService.getNotAssignedResources(pageNum, pageSize, tPResourceVO);
        return ResponseBean.success(tPResourceList);
    }

    /**
     * 批量分配资源
     */
    @PostMapping("/batchAllocationResource/{taskPackageId}")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:batch")
    @ControllerEndpoint(exceptionMessage = "批量分配资源失败",operation = "批量分配资源")
    public ResponseBean<String> batchAllocationResource(@RequestBody Map<String, List<Long>> batchAllocationMap,
                                                        @PathVariable(value = "taskPackageId",required = false) Integer taskPackageId){
        if (taskPackageId != null && taskPackageId>0){
            //将id传入TaskPackageResourceVO对象
            TaskPackageResourceVO tPResourceVO = new TaskPackageResourceVO();
            tPResourceVO.setTaskPackageId(taskPackageId);
            //调用查询方法
            PageVO<TaskPackageResource> tPResourceList = taskPackageResourceService.getNotAssignedResources(1, 10000, tPResourceVO);
            //将查询到的资源id存入list
            List<Long> resourceIdList = new ArrayList<>();
            for (TaskPackageResource tPResource : tPResourceList.getRows()) {
                resourceIdList.add(tPResource.getResourceId());
            }
            //将查询到的资源id存入batchAllocationMap
            batchAllocationMap.put("resourceIds", resourceIdList);
        }
        System.out.println(batchAllocationMap.get("resourceIds"));
        if (batchAllocationMap != null){
           int success =  taskPackageResourceService.batchAllocationResource(batchAllocationMap,taskPackageId);
            System.out.println(success);
            if (success>0){
                return ResponseBean.success("success");
            }else {
                return ResponseBean.success("fail");
            }
        }else {
            return ResponseBean.success("isNull");
        }
    }
    /**
     * 资源列表
     *
     * @return
     */
    @ApiOperation(value = "资源列表", notes = "模糊查询持有人")
    @GetMapping("/findIndustryVOList")
    @ResponseBody
    public List<Industry> findIndustryVOList(String accountName) {
//        List<Industry> industryList = industryService.findIndustryList();
        List<Industry> industryList = industryService.findIndustryList(accountName);
        return industryList;
    }

    /**
     * 导出excel
     * @param response
     */
    @ApiOperation(value = "导出excel", notes = "导出选中任务包所有任务资源的excel表格")
    @PostMapping("/excel/{taskPackageId}")
    @RequiresPermissions("taskpackage_resource:export")
    @ControllerEndpoint(exceptionMessage = "导出Excel失败",operation = "导出任务资源excel")
    public ResponseBean export(HttpServletResponse response, @PathVariable("taskPackageId") Integer taskPackageId) {
        //根据taskPackageId查询资源id
        TaskPackageResourceVO tPResourceVO = new TaskPackageResourceVO();
        tPResourceVO.setTaskPackageId(taskPackageId);
        PageVO<TaskPackageResource> tPResourceList = taskPackageResourceService.getAllResources(1, 10000, taskPackageId);
        //将查询到的资源id存入list
        List<Long> resourceIds = new ArrayList<>();
        for (TaskPackageResource tPResource : tPResourceList.getRows()) {
            resourceIds.add(tPResource.getResourceId());
        }
        System.out.println(resourceIds);
        //判断资源id列表是否为空，为空则向前台报出为空异常
        if (resourceIds== null || resourceIds.isEmpty()){
            //向前台报出为空
            return ResponseBean.success("isNull");
        }
        List<TaskPackageResource> tPResources = taskPackageResourceService.downTPExcel(resourceIds);
        ExcelKit.$Export(TaskPackageResource.class, response).downXlsx(tPResources, false);
        return ResponseBean.success("success");
    }
    /**
     * 批量导出excel
     * @param response
     */
    @ApiOperation(value = "导出excel", notes = "批量导出任务资源的excel表格")
    @PostMapping("/batchExport/{resourceIds}")
    @RequiresPermissions("taskpackage_resource:export")
    @ControllerEndpoint(exceptionMessage = "导出Excel失败",operation = "导出任务资源excel")
    public ResponseBean batchExport(HttpServletResponse response, @PathVariable("resourceIds") List<Long> resourceIds) {
        //判断资源id列表是否为空，为空则向前台报出为空异常
        if (resourceIds== null || resourceIds.size()==0){
            //向前台报出为空
            return ResponseBean.success("isNull");
        }
        List<TaskPackageResource> tPResources = taskPackageResourceService.downTPExcel(resourceIds);
        ExcelKit.$Export(TaskPackageResource.class, response).downXlsx(tPResources, false);
        return ResponseBean.success("success");
    }
    /**
     * 回收资源
     *
     * @param resourceIds 资源id列表
     * @return 回收的数量
     */
    @PostMapping("/recycleResources")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:recycle")
    @ControllerEndpoint(exceptionMessage = "回收资源失败",operation = "回收资源")
    public ResponseBean<String> recycleResources(@RequestBody(required = false) List<Long> resourceIds){
        System.out.println("====================="+resourceIds);
        int count = taskPackageResourceService.recycleResources(resourceIds);
        if (count>0){
            return ResponseBean.success("success");
        }else {
            return ResponseBean.success("isNull");
        }
    }
    /**
     * 批量回收资源
     *
     * @param taskPackageId 资源id列表
     * @return 回收的数量
     */
    @PostMapping("/batchRecycleResources")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:recycle")
    @ControllerEndpoint(exceptionMessage = "回收资源失败",operation = "回收资源")
    public ResponseBean<String> batchRecycleResources(@RequestBody Integer taskPackageId){
        System.out.println("====================="+taskPackageId);
        if (taskPackageId!= null){
            //根据taskPackageId查询资源id
            TaskPackageResourceVO tPResourceVO = new TaskPackageResourceVO();
            tPResourceVO.setTaskPackageId(taskPackageId);
            //根据taskPackageId查询资源id
            PageVO<TaskPackageResource> tPResourceList = taskPackageResourceService.getAllResources(1, 10000, taskPackageId);
            //将查询到的资源id存入list
            List<Long> resourceIds = new ArrayList<>();
            for (TaskPackageResource tPResource : tPResourceList.getRows()) {
                resourceIds.add(tPResource.getResourceId());
            }
            int count = taskPackageResourceService.recycleResources(resourceIds);
            if (count>0){
                return ResponseBean.success("success");
            }else {
                return ResponseBean.success("isNull");
            }
        }else {
            return ResponseBean.success("fail");
        }
    }
    /**
     * 根据资源id删除任务资源
     * @param resourceIds 资源id列表
     * @return 删除的数量
     */
    @PostMapping("/delByTPResourceId")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:del")
    @ControllerEndpoint(exceptionMessage = "删除任务资源失败",operation = "删除任务资源")
    public ResponseBean<String> delByTPResourceId(@RequestBody List<Long> resourceIds){
        if (resourceIds!= null){
            int count = taskPackageResourceService.delByTPResourceId(resourceIds);
            if (count>0){
                return ResponseBean.success("success");
            }else {
                return ResponseBean.success("fail");
            }
        }else {
            return ResponseBean.success("isNull");
        }
    }

    /**
     *  导入资源
     * @param file excel文件
     * @return 导入的资源列表
     * @throws Exception 异常
     */
    @PostMapping("/importResource")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:import")
    @ControllerEndpoint(exceptionMessage = "导入资源失败",operation = "导入资源")
    public ResponseMessage importResource(@RequestParam("file") MultipartFile file,
                                          @RequestParam("accountName")String accountName,
                                          @RequestParam("taskPackageId")Integer taskPackageId) throws Exception {
        //创建表格规则
        Map<String,String> map = new HashMap<>();
        map.put("客户名称","resourceName");
        map.put("电话A","phoneA");
        map.put("电话B","phoneB");
        map.put("联系人姓名","linkman");
        map.put("备注","remark");
        //解析表格
        List<ResourceInfoVO> list =ExcelUtils.parseExcel(file,ResourceInfoVO.class,map);
        // 参数校验
        if (list.size() > 50000) {
            return ResponseMessage.error("您导入的数据量过大,请控制在50000条以内");
        }
        //去重
        List<ResourceInfoVO> newlist = ExcelUtils.deWeight(list);
        //二次去重（数据库去重）
        List<ResourceInfoVO> newlist2 = taskPackageResourceService.sqlDeWeight(newlist);
        // 参数校验
        if (newlist2.isEmpty()) {
            return ResponseMessage.error("您导入的数据与已有资源重复,操作已结束");
        }
        //调用导入资源方法
        String context = taskPackageResourceService.importResource(newlist2,taskPackageId,accountName);
        if (context.equals("success")){
            return ResponseMessage.success("success");
        }else {
            return ResponseMessage.error(context);
        }
    }
    /**
     *  新增任务包
     *
     * @return 新增的任务包
     */
    @PostMapping("/addTaskPackage")
    @ResponseBody
    @RequiresPermissions("task_package:add")
    @ControllerEndpoint(exceptionMessage = "新增任务包失败", operation = "新增任务包")
    public ResponseMessage addTaskPackage(@RequestParam("taskPackageName") String taskPackageName,
                                                  @RequestParam(value = "accountName",required = false) String accountName,
                                                  @RequestParam(value ="userId",required = false) Long userId,
                                                  @RequestParam("file") MultipartFile file) throws Exception {
        TaskPackageVO taskPackageVO = new TaskPackageVO();
        taskPackageVO.setTaskPackageName(taskPackageName);
        if (accountName != null){
            taskPackageVO.setAccountName(accountName);
        }
        if (userId != null){
            taskPackageVO.setUserId(userId);
        }
        // 创建表格规则
        Map<String, String> map = new HashMap<>();
        map.put("客户名称", "resourceName");
        map.put("电话A", "phoneA");
        map.put("电话B", "phoneB");
        map.put("联系人姓名", "linkman");
        map.put("备注", "remark");
        // 解析表格
        List<ResourceInfoVO> list = ExcelUtils.parseExcel(file,ResourceInfoVO.class,map);
        // 参数校验
        if (list.size() > 50000) {
            return ResponseMessage.error("您导入的数据量过大,请控制在50000条以内");
        }
        //去重
        List<ResourceInfoVO> newlist = ExcelUtils.deWeight(list);
        //二次去重
        List<ResourceInfoVO> newlist2 = taskPackageResourceService.sqlDeWeight(newlist);
        // 参数校验
        if (newlist2.isEmpty()) {
            return ResponseMessage.error("您导入的数据与已有资源重复,操作已结束");
        }
        
        // 记录开始时间用于计算耗时
        long startTime = System.currentTimeMillis();
        
        //调用创建任务包方法
        String context = taskPackageResourceService.createTaskPackage(newlist2, taskPackageVO);
        
        // 计算耗时（秒）
        double importTimeSeconds = (System.currentTimeMillis() - startTime) / 1000.0;
        
        if (context.equals("success")){
            // 创建统计信息
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalRows", list.size());
            stats.put("importedRows", newlist2.size());
            stats.put("importTimeSeconds", importTimeSeconds);
            
            // 创建响应对象
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("status", "success");
            responseData.put("stats", stats);
            
            return ResponseMessage.success(responseData);
        } else {
            return ResponseMessage.error(context);
        }
    }


    /**
     * 根据手机号查重
     * @param taskPackageIds 传入的任务包编号（用来判断查重方式）
     * @return 处理的数量
     */
    @PostMapping("/findDuplicatePhones")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:findDuplicate")
    @ControllerEndpoint(exceptionMessage = "回收资源失败",operation = "回收资源")
    public ResponseMessage findDuplicatePhones(@RequestBody List<Integer> taskPackageIds){
        Integer count = taskPackageResourceService.findDuplicatePhones(taskPackageIds);
        if ( count>0 ){
            return ResponseMessage.success("success");
        }else {
            return ResponseMessage.success("isNull");
        }
    }

    /**
     * 处理文件分片上传
     * 
     * @param chunk 当前分片
     * @param index 当前分片索引
     * @param total 总分片数
     * @param filename 原始文件名
     * @return 上传结果
     */
    @PostMapping("/uploadChunk")
    @ResponseBody
    public ResponseBean<Map<String, Object>> uploadChunk(
            @RequestParam("chunk") MultipartFile chunk,
            @RequestParam("index") int index,
            @RequestParam("total") int total,
            @RequestParam("filename") String filename,
            @RequestParam(value = "uploadId", required = false) String uploadId) {
        
        try {
            // 如果没有提供uploadId，则为第一个分片生成唯一标识符
            if (uploadId == null || uploadId.isEmpty()) {
                uploadId = UUID.randomUUID().toString();
            }
            
            // 创建临时目录
            File uploadDir = new File(tempPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }
            
            File uploadIdDir = new File(uploadDir, uploadId);
            if (!uploadIdDir.exists()) {
                uploadIdDir.mkdirs();
            }
            
            // 保存分片
            File chunkFile = new File(uploadIdDir, String.valueOf(index));
            try (FileOutputStream fos = new FileOutputStream(chunkFile)) {
                InputStream is = chunk.getInputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                }
            }
            
            // 更新进度
            int progress = (index + 1) * 100 / total;
            UPLOAD_PROGRESS.put(uploadId, progress);
            
            Map<String, Object> result = new HashMap<>();
            result.put("uploadId", uploadId);
            result.put("progress", progress);
            
            return ResponseBean.success(result);
        } catch (IOException e) {
            e.printStackTrace();
            Map<String, Object> error = new HashMap<>();
            error.put("message", "分片上传失败: " + e.getMessage());
            return ResponseBean.error(error);
        }
    }
    
    /**
     * 上传单个文件（非分片）
     * 
     * @param file 上传的文件
     * @return 上传结果
     */
    @PostMapping("/uploadSingleFile")
    @ResponseBody
    public ResponseBean<Map<String, Object>> uploadSingleFile(@RequestParam("file") MultipartFile file) {
        try {
            // 检查文件是否为空
            if (file.isEmpty()) {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("message", "上传的文件为空");
                return ResponseBean.error(errorResult);
            }
            
            log.info("开始处理单个文件上传，文件名: {}", file.getOriginalFilename());
            
            // 生成唯一的文件名
            String uploadId = String.valueOf(System.currentTimeMillis());
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            
            // 使用完全的绝对路径
            String baseTempDir = System.getProperty("java.io.tmpdir");
            if (baseTempDir.endsWith(File.separator)) {
                baseTempDir = baseTempDir.substring(0, baseTempDir.length() - 1);
            }
            
            // 创建临时文件目录，避免使用相对路径
            String uploadTempPath = baseTempDir + File.separator + "easygem-upload";
            
            // 创建目录结构
            File uploadDir = new File(uploadTempPath);
            if (!uploadDir.exists() && !uploadDir.mkdirs()) {
                throw new IOException("无法创建上传目录: " + uploadTempPath);
            }
            
            // 创建并保存文件
            String filename = uploadId + extension;
            File uploadFile = new File(uploadDir, filename);
            String absoluteFilePath = uploadFile.getAbsolutePath();
            
            log.info("保存文件到: {}", absoluteFilePath);
            file.transferTo(uploadFile);
            
            // 检查文件是否成功创建
            if (!uploadFile.exists()) {
                throw new IOException("文件保存失败，无法找到文件: " + absoluteFilePath);
            }
            
            log.info("文件保存成功: {}，大小: {} 字节", absoluteFilePath, uploadFile.length());
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("mergedFilename", absoluteFilePath);
            result.put("originalFilename", originalFilename);
            
            return ResponseBean.success(result);
        } catch (Exception e) {
            log.error("上传单个文件失败: {}", e.getMessage(), e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("message", "上传文件失败: " + e.getMessage());
            return ResponseBean.error(errorResult);
        }
    }
    
    /**
     * 合并文件分片
     * 
     * @param request 请求参数包含filename、uploadId和totalChunks
     * @return 合并结果
     */
    @PostMapping("/mergeChunks")
    @ResponseBody
    public ResponseBean<Map<String, Object>> mergeChunks(@RequestBody Map<String, Object> request) {
        String filename = (String) request.get("filename");
        String uploadId = (String) request.get("uploadId");
        int totalChunks = Integer.parseInt(request.get("totalChunks").toString());
        
        try {
            // 临时文件目录
            File tempDir = new File(tempPath, uploadId);
            if (!tempDir.exists()) {
                Map<String, Object> error = new HashMap<>();
                error.put("message", "上传ID不存在或已过期");
                return ResponseBean.error(error);
            }
            
            // 创建合并后的文件
            String fileExtension = filename.substring(filename.lastIndexOf("."));
            String mergedFilename = UUID.randomUUID().toString() + fileExtension;
            File mergedFile = new File(tempPath, mergedFilename);
            
            try (FileOutputStream fos = new FileOutputStream(mergedFile)) {
                // 按顺序合并所有分片
                for (int i = 0; i < totalChunks; i++) {
                    File chunkFile = new File(tempDir, String.valueOf(i));
                    if (!chunkFile.exists()) {
                        Map<String, Object> error = new HashMap<>();
                        error.put("message", "分片文件缺失: " + i);
                        return ResponseBean.error(error);
                    }
                    
                    Files.copy(chunkFile.toPath(), fos);
                }
            }
            
            // 清理分片文件
            for (File chunk : tempDir.listFiles()) {
                chunk.delete();
            }
            tempDir.delete();
            
            // 移除进度记录
            UPLOAD_PROGRESS.remove(uploadId);
            
            // 返回完整的绝对路径
            String absoluteFilePath = mergedFile.getAbsolutePath();
            
            // 打印最终文件路径用于调试
            System.out.println("合并后的文件保存到: " + absoluteFilePath);
            
            Map<String, Object> result = new HashMap<>();
            result.put("mergedFilename", absoluteFilePath);
            result.put("originalFilename", filename);
            
            return ResponseBean.success(result);
        } catch (IOException e) {
            e.printStackTrace();
            Map<String, Object> error = new HashMap<>();
            error.put("message", "文件合并失败: " + e.getMessage());
            return ResponseBean.error(error);
        }
    }
    
    /**
     * 大数据量Excel导入任务包资源
     * 
     * @param request 请求体，包含合并后的文件名、任务包ID和账户名
     * @return 导入结果
     */
    @PostMapping("/importLargeResource")
    @ResponseBody
    @RequiresPermissions("taskpackage_resource:import")
    @ControllerEndpoint(exceptionMessage = "大数据量导入资源失败", operation = "大数据量导入资源")
    public ResponseBean<Map<String, Object>> importLargeResource(@RequestBody Map<String, Object> request) {
        String mergedFilename = (String) request.get("mergedFilename");
        Integer taskPackageId = Integer.valueOf(request.get("taskPackageId").toString());
        String accountName = (String) request.get("accountName");
        
        // 使用完整路径，不再拼接tempPath
        File excelFile = new File(mergedFilename);
        if (!excelFile.exists()) {
            Map<String, Object> error = new HashMap<>();
            error.put("message", "文件不存在或已过期");
            return ResponseBean.error(error);
        }
        
        try {
            // 创建导入任务ID
            String importId = UUID.randomUUID().toString();
            
            // 异步处理导入
            new Thread(() -> {
                try {
                    processLargeExcelImport(excelFile, taskPackageId, accountName, importId);
                } catch (Exception e) {
                    e.printStackTrace();
                    // 记录导入失败状态
                    UPLOAD_PROGRESS.put("import_" + importId, -1); // 使用-1表示出错
                }
            }).start();
            
            Map<String, Object> result = new HashMap<>();
            result.put("importId", importId);
            result.put("status", "started");
            
            return ResponseBean.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            Map<String, Object> error = new HashMap<>();
            error.put("message", "导入初始化失败: " + e.getMessage());
            return ResponseBean.error(error);
        }
    }
    
    /**
     * 查询导入进度
     * 
     * @param importId 导入任务ID
     * @return 导入进度
     */
    @GetMapping("/importProgress")
    @ResponseBody
    public ResponseBean<Map<String, Object>> importProgress(@RequestParam("importId") String importId) {
        Integer progress = UPLOAD_PROGRESS.getOrDefault("import_" + importId, 0);
        
        Map<String, Object> result = new HashMap<>();
        if (progress < 0) {
            result.put("status", "error");
            result.put("message", "导入处理失败");
        } else if (progress >= 100) {
            result.put("status", "completed");
            result.put("progress", 100);
        } else {
            result.put("status", "processing");
            result.put("progress", progress);
        }
        
        return ResponseBean.success(result);
    }
    
    /**
     * 处理大数据量Excel导入
     */
    private void processLargeExcelImport(File excelFile, Integer taskPackageId, String accountName, String importId) throws Exception {
        // 1. 设置初始进度
        UPLOAD_PROGRESS.put("import_" + importId, 0);
        
        // 2. 创建表格规则
        Map<String, String> fieldMapping = new HashMap<>();
        fieldMapping.put("客户名称", "resourceName");
        fieldMapping.put("电话A", "phoneA");
        fieldMapping.put("电话B", "phoneB");
        fieldMapping.put("联系人姓名", "linkman");
        fieldMapping.put("备注", "remark");
        
        try {
            // 3. 使用流式解析处理大文件
            int totalRows = ExcelUtils.countRows(excelFile);
            final int[] processedRows = {0}; // 使用数组包装，以便在lambda中修改
            int batchSize = 5000; // 批处理大小
            
            // 4. 分批处理数据
            ExcelUtils.processExcelInBatches(excelFile, ResourceInfoVO.class, fieldMapping, 
                    (batch, isLast) -> {
                try {
                    if (!batch.isEmpty()) {
                        // 增量更新进度 (当前处理行数/总行数)
                        processedRows[0] += batch.size();
                        int progress = (int) ((double) processedRows[0] / totalRows * 100);
                        UPLOAD_PROGRESS.put("import_" + importId, Math.min(99, progress)); // 留1%给最终处理
                        
                        // 批量导入到数据库
                        taskPackageResourceService.batchImportResource(batch, taskPackageId, accountName);
                    }
                    
                    // 最后一批，设置100%完成
                    if (isLast) {
                        UPLOAD_PROGRESS.put("import_" + importId, 100);
                    }
                } catch (Exception e) {
                    UPLOAD_PROGRESS.put("import_" + importId, -1); // 错误状态
                    throw new RuntimeException("批处理导入失败: " + e.getMessage(), e);
                }
            }, batchSize);
            
            // 5. 清理临时文件
            excelFile.delete();
        } catch (org.apache.poi.openxml4j.exceptions.InvalidFormatException e) {
            // 记录错误状态
            UPLOAD_PROGRESS.put("import_" + importId, -1);
            throw new RuntimeException("Excel文件格式错误: " + e.getMessage(), e);
        } catch (Exception e) {
            // 记录错误状态
            UPLOAD_PROGRESS.put("import_" + importId, -1);
            throw e; // 重新抛出异常
        }
    }

    /**
     * 创建大文件任务包 - 用于处理大数据量Excel文件
     * 
     * @param request 请求体，包含任务包信息和合并后的文件名
     * @return 导入任务ID
     */
    @PostMapping("/createLargeTaskPackage")
    @ResponseBody
    @RequiresPermissions("task_package:add")
    @ControllerEndpoint(exceptionMessage = "创建大型任务包失败", operation = "创建大型任务包")
    public ResponseBean<Map<String, Object>> createLargeTaskPackage(@RequestBody Map<String, Object> request) {
        try {
            String mergedFilename = (String) request.get("mergedFilename");
            String taskPackageName = (String) request.get("taskPackageName");
            
            // 改进userId参数处理，处理空字符串情况
            Long userId = null;
            Object userIdObj = request.get("userId");
            if (userIdObj != null && !String.valueOf(userIdObj).trim().isEmpty()) {
                try {
                    userId = Long.valueOf(String.valueOf(userIdObj));
                } catch (NumberFormatException e) {
                    System.out.println("无效的userId: " + userIdObj);
                    // 继续执行，userId保持为null
                }
            }
            
            String accountName = (String) request.get("accountName");
            
            // 记录请求参数
            System.out.println("创建大型任务包请求参数: " + request);
            System.out.println("处理后的参数 - mergedFilename: " + mergedFilename + 
                             ", taskPackageName: " + taskPackageName + 
                             ", userId: " + userId + 
                             ", accountName: " + accountName);
            
            if (mergedFilename == null || taskPackageName == null) {
                Map<String, Object> error = new HashMap<>();
                error.put("message", "缺少必要参数");
                return ResponseBean.error(error);
            }
            
            // 验证文件是否存在
            File excelFile = new File(mergedFilename);
            System.out.println("检查文件是否存在: " + mergedFilename);
            System.out.println("文件是否存在: " + excelFile.exists());
            System.out.println("文件大小: " + (excelFile.exists() ? excelFile.length() : "不存在"));
            
            if (!excelFile.exists()) {
                Map<String, Object> error = new HashMap<>();
                error.put("message", "上传的文件不存在或已被删除: " + mergedFilename);
                return ResponseBean.error(error);
            }
            
            // 验证文件是否可读
            if (!excelFile.canRead()) {
                Map<String, Object> error = new HashMap<>();
                error.put("message", "文件无法读取，请检查权限: " + mergedFilename);
                return ResponseBean.error(error);
            }
            
            // 创建任务包对象
            TaskPackageVO taskPackageVO = new TaskPackageVO();
            taskPackageVO.setTaskPackageName(taskPackageName);
            if (userId != null) {
                taskPackageVO.setUserId(userId);
            }
            if (accountName != null) {
                taskPackageVO.setAccountName(accountName);
            }
            
            // 创建任务包并获取任务包ID
            TaskPackage taskPackage = new TaskPackage();
            BeanUtils.copyProperties(taskPackageVO, taskPackage);
            
            // 设置创建时间
            taskPackage.setCreateTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
            
            // 保存任务包
            log.info("准备保存任务包: {}", taskPackage);
            int insertResult = taskPackageMapper.addTaskPackage(taskPackage);
            if (insertResult <= 0) {
                Map<String, Object> error = new HashMap<>();
                error.put("message", "任务包创建失败");
                return ResponseBean.error(error);
            }
            
            // 获取任务包ID
            final Integer taskPackageId = taskPackage.getTaskPackageId();
            System.out.println("成功创建任务包，ID: " + taskPackageId);
            
            // 添加任务包ID到VO对象中，避免Service层再创建一次
            taskPackageVO.setTaskPackageId(taskPackageId);
            
            // 创建导入统计对象
            ImportStats stats = new ImportStats(500); // 使用默认批次大小
            importTaskStats.put(taskPackageId, stats);
            
            // 异步处理任务包创建
            new Thread(() -> {
                try {
                    System.out.println("开始导入任务包资源，文件路径: " + mergedFilename + "，任务包ID: " + taskPackageId);
                    String result = taskPackageResourceService.createLargeTaskPackage(mergedFilename, taskPackageVO);
                    System.out.println("任务包资源导入结果: " + result);
                    
                    if (!"success".equals(result)) {
                        // 记录导入失败状态
                        Map<String, Object> statsMap = taskPackageResourceService.getImportStats(taskPackageId);
                        if (statsMap != null && !statsMap.containsKey("errorMessage")) {
                            ((ImportStats)importTaskStats.get(taskPackageId)).setError("任务包创建失败: " + result);
                        }
                    }
                } catch (Exception e) {
                    System.err.println("创建任务包异常: " + e.getMessage());
                    e.printStackTrace();
                    // 记录导入失败状态
                    ((ImportStats)importTaskStats.get(taskPackageId)).setError("处理异常: " + e.getMessage());
                }
            }).start();
            
            Map<String, Object> result = new HashMap<>();
            result.put("importId", String.valueOf(taskPackageId));
            result.put("taskPackageId", taskPackageId);  // 返回实际的任务包ID
            result.put("status", "started");
            
            return ResponseBean.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            Map<String, Object> error = new HashMap<>();
            error.put("message", "创建任务包初始化失败: " + e.getMessage());
            return ResponseBean.error(error);
        }
    }

    /**
     * 获取任务包导入进度统计信息
     * @param taskPackageId 任务包ID
     * @return 导入进度统计信息
     */
    @GetMapping("/importStats/{taskPackageId}")
    @ResponseBody
    public ResponseBean<Map<String, Object>> getImportStats(@PathVariable("taskPackageId") Integer taskPackageId) {
        try {
            log.info("获取导入统计信息，任务包ID: {}", taskPackageId);
            Map<String, Object> stats = taskPackageResourceService.getImportStats(taskPackageId);
            
            if (stats != null) {
                // 为前端提供更友好的状态描述
                String status = (String) stats.get("status");
                String statusDesc = "";
                String progressDesc = "";
                
                if ("uploading".equals(status)) {
                    statusDesc = "正在上传文件...";
                } else if ("importing".equals(status)) {
                    Object progress = stats.get("progress");
                    double progressValue = progress instanceof Number ? ((Number) progress).doubleValue() : 0;
                    int progressInt = (int) Math.floor(progressValue);
                    
                    statusDesc = "正在导入资源...";
                    progressDesc = "已处理 " + stats.get("processedRows") + 
                                   " 行，成功导入 " + stats.get("importedRows") + 
                                   " 条记录 (" + progressInt + "%)";
                } else if ("completed".equals(status)) {
                    statusDesc = "导入完成";
                    progressDesc = "共导入 " + stats.get("importedRows") + " 条记录，用时 " + 
                                   stats.get("importTimeSeconds") + " 秒";
                } else if ("error".equals(status)) {
                    statusDesc = "导入出错";
                    progressDesc = stats.containsKey("errorMessage") ? (String) stats.get("errorMessage") : "未知错误";
                } else if ("partial_error".equals(status)) {
                    statusDesc = "部分导入成功";
                    progressDesc = "已导入 " + stats.get("importedRows") + 
                                   " 条记录，但有部分数据导入失败：" + 
                                   (stats.containsKey("errorMessage") ? stats.get("errorMessage") : "未知错误");
                }
                
                // 将友好描述添加到返回结果
                stats.put("statusDesc", statusDesc);
                stats.put("progressDesc", progressDesc);
                
                return ResponseBean.success(stats);
            } else {
                // 如果找不到统计信息，返回一个默认的进度状态
                Map<String, Object> defaultStats = new HashMap<>();
                defaultStats.put("status", "not_found");
                defaultStats.put("statusDesc", "找不到导入任务");
                defaultStats.put("progressDesc", "找不到任务包ID: " + taskPackageId + " 的导入任务");
                
                return ResponseBean.success(defaultStats);
            }
        } catch (Exception e) {
            log.error("获取导入统计信息出错: {}", e.getMessage(), e);
            
            Map<String, Object> errorStats = new HashMap<>();
            errorStats.put("status", "error");
            errorStats.put("statusDesc", "获取统计信息出错");
            errorStats.put("progressDesc", e.getMessage());
            errorStats.put("errorMessage", e.getMessage());
            
            return ResponseBean.success(errorStats);
        }
    }

    /**
     * 上传单个文件并自动创建任务包 - 一步到位处理
     *
     * @param file 文件
     * @param taskPackageName 任务包名称
     * @param accountName 账户名称
     * @param userId 用户ID
     * @return 上传和创建结果
     */
    @PostMapping("/uploadFileAndCreatePackage")
    @ResponseBody
    @RequiresPermissions("task_package:add")
    @ControllerEndpoint(exceptionMessage = "上传文件并创建任务包失败", operation = "上传文件并创建任务包")
    public ResponseBean<Map<String, Object>> uploadFileAndCreatePackage(
            @RequestParam("file") MultipartFile file,
            @RequestParam("taskPackageName") String taskPackageName,
            @RequestParam(value = "accountName", required = false) String accountName,
            @RequestParam(value = "userId", required = false) Long userId) {
        try {
            // 检查文件是否为空
            if (file.isEmpty()) {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("message", "上传的文件为空");
                return ResponseBean.error(errorResult);
            }
            
            log.info("开始处理文件上传和任务包创建，文件名: {}, 任务包名: {}", 
                    file.getOriginalFilename(), taskPackageName);
            
            // 1. 保存文件部分
            // 生成唯一的文件名
            String uploadId = String.valueOf(System.currentTimeMillis());
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            
            // 使用完全的绝对路径
            String baseTempDir = System.getProperty("java.io.tmpdir");
            if (baseTempDir.endsWith(File.separator)) {
                baseTempDir = baseTempDir.substring(0, baseTempDir.length() - 1);
            }
            
            // 创建临时文件目录，避免使用相对路径
            String uploadTempPath = baseTempDir + File.separator + "easygem-upload";
            
            // 创建目录结构
            File uploadDir = new File(uploadTempPath);
            if (!uploadDir.exists() && !uploadDir.mkdirs()) {
                throw new IOException("无法创建上传目录: " + uploadTempPath);
            }
            
            // 创建并保存文件
            String filename = uploadId + extension;
            File uploadFile = new File(uploadDir, filename);
            String absoluteFilePath = uploadFile.getAbsolutePath();
            
            log.info("保存文件到: {}", absoluteFilePath);
            file.transferTo(uploadFile);
            
            // 检查文件是否成功创建
            if (!uploadFile.exists()) {
                throw new IOException("文件保存失败，无法找到文件: " + absoluteFilePath);
            }
            
            log.info("文件保存成功: {}，大小: {} 字节", absoluteFilePath, uploadFile.length());
            
            // 2. 创建任务包部分
            // 创建任务包对象
            TaskPackageVO taskPackageVO = new TaskPackageVO();
            taskPackageVO.setTaskPackageName(taskPackageName);
            if (userId != null) {
                taskPackageVO.setUserId(userId);
            }
            if (accountName != null) {
                taskPackageVO.setAccountName(accountName);
            }
            
            // 创建任务包并获取任务包ID
            TaskPackage taskPackage = new TaskPackage();
            BeanUtils.copyProperties(taskPackageVO, taskPackage);
            
            // 设置创建时间
            taskPackage.setCreateTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
            
            // 保存任务包
            log.info("准备保存任务包: {}", taskPackage);
            int insertResult = taskPackageMapper.addTaskPackage(taskPackage);
            if (insertResult <= 0) {
                throw new IOException("任务包创建失败");
            }
            
            // 获取任务包ID
            final Integer taskPackageId = taskPackage.getTaskPackageId();
            log.info("成功创建任务包，ID: {}", taskPackageId);
            
            // 将任务包ID添加到VO对象，避免Service层再创建一次
            taskPackageVO.setTaskPackageId(taskPackageId);
            
            // 创建导入统计对象
            ImportStats stats = new ImportStats(500); // 使用默认批次大小
            importTaskStats.put(taskPackageId, stats);
            
            // 3. 异步处理任务包创建和资源导入
            new Thread(() -> {
                try {
                    log.info("开始导入任务包资源，文件路径: {}，任务包ID: {}", absoluteFilePath, taskPackageId);
                    String result = taskPackageResourceService.createLargeTaskPackage(absoluteFilePath, taskPackageVO);
                    log.info("任务包资源导入结果: {}", result);
                    
                    if (!"success".equals(result)) {
                        // 记录导入失败状态
                        Map<String, Object> statsMap = taskPackageResourceService.getImportStats(taskPackageId);
                        if (statsMap != null && !statsMap.containsKey("errorMessage")) {
                            ImportStats importStats = importTaskStats.get(taskPackageId);
                            if (importStats != null) {
                                importStats.setError("任务包创建失败: " + result);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("创建任务包异常: {}", e.getMessage(), e);
                    // 记录导入失败状态
                    ImportStats importStats = importTaskStats.get(taskPackageId);
                    if (importStats != null) {
                        importStats.setError("任务包创建异常: " + e.getMessage());
                    }
                }
            }).start();
            
            // 4. 构建返回信息
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("taskPackageId", taskPackageId);
            resultMap.put("taskPackageName", taskPackageName);
            resultMap.put("status", "started");
            resultMap.put("message", "任务包资源导入已开始，请前往进度页面查看详情");
            
            // 5. 添加进度页面URL
            String progressUrl = "/tasking/importProgress?taskPackageId=" + taskPackageId + 
                         "&packageName=" + URLEncoder.encode(taskPackageName, "UTF-8");
            resultMap.put("progressUrl", progressUrl);
            
            return ResponseBean.success(resultMap);
        } catch (Exception e) {
            log.error("上传文件并创建任务包失败: {}", e.getMessage(), e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("message", "上传文件并创建任务包失败: " + e.getMessage());
            return ResponseBean.error(errorResult);
        }
    }
}
